import type { FastifyBaseLogger } from "fastify";

let baseLogger: FastifyBaseLogger;

/**
 * 获取日志配置对象
 * @param name 日志名称
 * @param debug 调试模式
 * @returns 日志配置对象
 */
export function getLoggerConfig(name = "app", debug = false) {
	const loggerConfig: any = {
		name,
		level: debug ? "debug" : "warn",
	};
	if (debug) {
		loggerConfig.transport = {
			target: "pino-smart",
		};
	}
	return loggerConfig;
}

/**
 * 初始化日志记录器
 * @param logger 日志记录器
 */
export function initLogger(logger: FastifyBaseLogger) {
	baseLogger = logger;
}

interface LogMessageOption {
	level?: "debug" | "info" | "warn" | "error";
	msg: any;
	msgPrefix?: string;
	name?: string;
	logger?: FastifyBaseLogger;
}

/**
 * 打印 [INFO] 信息日志
 *
 * @param msg - 日志消息
 */
export function info(
	msg: LogMessageOption | string | boolean | number | object,
) {
	let logOption: LogMessageOption = { msg };
	if (Object.hasOwn(logOption.msg as object, "msg")) {
		logOption = logOption.msg as LogMessageOption;
	}
	logOption.level = "info";
	log(logOption);
}

/**
 * 输出日志
 *
 * @param msg - 日志内容
 */
export function log(
	msg: LogMessageOption | string | boolean | number | object,
) {
	let defaultLogOption: LogMessageOption = {
		level: "info",
		msg,
		msgPrefix: "",
		name: "app",
		logger: baseLogger,
	};

	// 如果传入的对象包含msg属性，则将defaultLogOption设置为该对象
	if (Object.hasOwn(msg as object, "msg")) {
		defaultLogOption = { ...(msg as LogMessageOption) };
	}

	// 如果defaultLogOption.msg是对象，则尝试将其转换为JSON字符串，如果转换失败则转为字符串
	if (typeof defaultLogOption.msg === "object") {
		try {
			defaultLogOption.msg = JSON.stringify(defaultLogOption.msg);
		} catch (e) {
			defaultLogOption.msg = defaultLogOption.msg.toString();
		}
	} else {
		defaultLogOption.msg = `${defaultLogOption.msg}`;
	}

	// 如果设置了msgPrefix，则在msg前添加msgPrefix
	if (defaultLogOption.msgPrefix) {
		defaultLogOption.msg = `${defaultLogOption.msgPrefix}: ${defaultLogOption.msg}`;
	}
	// 调用logger以defaultLogOption指定的日志级别进行日志输出
	defaultLogOption.logger[defaultLogOption.level]({
		msg: defaultLogOption.msg,
		name: defaultLogOption.name,
	});
}
